// 《围棋》作者版权所有。保留所有权利。
// 此源代码的使用受BSD样式
// 许可证的约束，该许可证可以在许可证文件中找到。

// go:generate go run generate_zipdata。go 

// 包tzdata提供时区数据库的嵌入式副本。
// 如果这个包被导入程序中的任何地方，那么如果
// 时间包在系统上找不到tzdata文件，
// 它将使用这个嵌入的信息。
// 
// 导入此包将使程序大小增加约
// 450 KB。
// 
// 此包通常应由程序的主包导入，而不是由库导入。库通常不应该决定是否在程序中包含时区数据库。
// 
// 如果使用
// /-tags timetzdata进行构建，将自动导入此包。
package tzdata

// 这个软件包的测试是time/tzdata_测试。去

import (
	"errors"
	"syscall"
	_ "unsafe" // 对于go:linkname 
)

// registerLoadFromEmbeddedTZData在包时定义。wen jian defg
func registerLoadFromEmbeddedTZData(func(string) (string, error))

func init() {
	registerLoadFromEmbeddedTZData(loadFromEmbeddedTZData)
}

// get4s返回s开头的小尾端32位值。
func get4s(s string) int {
	if len(s) < 4 {
		return 0
	}
	return int(s[0]) | int(s[1])<<8 | int(s[2])<<16 | int(s[3])<<24
}

// get2s返回s开头的小尾端16位值。
func get2s(s string) int {
	if len(s) < 2 {
		return 0
	}
	return int(s[0]) | int(s[1])<<8
}

// loadFromEmbeddedTZData返回未压缩zip文件中具有给定
// 名称的文件内容，其中文件的内容可以在embeddedTzdata中找到。这和时间差不多。loadTzinfoFromZip。
func loadFromEmbeddedTZData(name string) (string, error) {
	const (
		zecheader = 0x06054b50
		zcheader  = 0x02014b50
		ztailsize = 22

		zheadersize = 30
		zheader     = 0x04034b50
	)

	z := zipdata

	idx := len(z) - ztailsize
	n := get2s(z[idx+10:])
	idx = get4s(z[idx+16:])

	for i := 0; i < n; i++ {
		// 见时间。loadTzinfoFromZip用于zip条目布局。
		if get4s(z[idx:]) != zcheader {
			break
		}
		meth := get2s(z[idx+10:])
		size := get4s(z[idx+24:])
		namelen := get2s(z[idx+28:])
		xlen := get2s(z[idx+30:])
		fclen := get2s(z[idx+32:])
		off := get4s(z[idx+42:])
		zname := z[idx+46 : idx+46+namelen]
		idx += 46 + namelen + xlen + fclen
		if zname != name {
			continue
		}
		if meth != 0 {
			return "", errors.New("unsupported compression for " + name + " in embedded tzdata")
		}

		// 见时间。loadTzinfoFromZip用于每个文件头的zip布局。
		idx = off
		if get4s(z[idx:]) != zheader ||
			get2s(z[idx+8:]) != meth ||
			get2s(z[idx+26:]) != namelen ||
			z[idx+30:idx+30+namelen] != name {
			return "", errors.New("corrupt embedded tzdata")
		}
		xlen = get2s(z[idx+28:])
		idx += 30 + namelen + xlen
		return z[idx : idx+size], nil
	}

	return "", syscall.ENOENT
}
